package main

import (
	"encoding/gob"
	"fmt"
	"os"
	"sync"
	"time"
)

// 缓存项结构体
type Item struct {
	Value    string
	ExpireAt time.Time
}

// 缓存组件
type Cache struct {
	mu      sync.RWMutex
	data    map[string]Item
	saveDir string
}

// 创建一个新的缓存实例
func NewCache(saveDir string) *Cache {
	c := &Cache{
		data:    make(map[string]Item),
		saveDir: saveDir,
	}
	go c.cleanupLoop(1 * time.Minute) // 每分钟清理一次过期项
	return c
}

// 设置 key-value
func (c *Cache) Set(key, value string) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.data[key] = Item{
		Value: value,
	}
}

// 获取 value
func (c *Cache) Get(key string) (string, bool) {
	c.mu.RLock()
	defer c.mu.RUnlock()
	item, found := c.data[key]
	if !found {
		return "", false
	}
	if !item.ExpireAt.IsZero() && time.Now().After(item.ExpireAt) {
		return "", false
	}
	return item.Value, found
}

// 设置带过期时间的 key-value
func (c *Cache) SetWithExpire(key, value string, duration time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.data[key] = Item{
		Value:    value,
		ExpireAt: time.Now().Add(duration),
	}
}

// 获取 value 和过期时间
func (c *Cache) GetWithExpire(key string) (string, time.Time, bool) {
	c.mu.RLock()
	defer c.mu.RUnlock()
	item, found := c.data[key]
	if !found {
		return "", time.Time{}, false
	}
	if !item.ExpireAt.IsZero() && time.Now().After(item.ExpireAt) {
		return "", time.Time{}, false
	}
	return item.Value, item.ExpireAt, true
}

// 获取 key 的过期时间
func (c *Cache) GetExpire(key string) (time.Time, bool) {
	c.mu.RLock()
	defer c.mu.RUnlock()
	item, found := c.data[key]
	if !found {
		return time.Time{}, false
	}
	return item.ExpireAt, true
}

// 设置 key 的过期时间
func (c *Cache) SetExpire(key string, duration time.Duration) bool {
	c.mu.Lock()
	defer c.mu.Unlock()
	item, found := c.data[key]
	if !found {
		return false
	}
	item.ExpireAt = time.Now().Add(duration)
	c.data[key] = item
	return true
}

// 清理过期项
func (c *Cache) cleanupLoop(interval time.Duration) {
	ticker := time.NewTicker(interval)
	defer ticker.Stop()
	for {
		<-ticker.C
		now := time.Now()
		c.mu.Lock()
		for k, v := range c.data {
			if !v.ExpireAt.IsZero() && now.After(v.ExpireAt) {
				delete(c.data, k)
			}
		}
		c.mu.Unlock()
	}
}

// 保存缓存到文件（持久化）
func (c *Cache) SaveToFile(filename string) error {
	c.mu.RLock()
	defer c.mu.RUnlock()
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	enc := gob.NewEncoder(file)
	err = enc.Encode(c.data)
	if err != nil {
		return err
	}
	return nil
}

// 从文件加载缓存
func (c *Cache) LoadFromFile(filename string) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	dec := gob.NewDecoder(file)
	err = dec.Decode(&c.data)
	if err != nil {
		return err
	}
	return nil
}

// 主函数测试
func main() {
	cache := NewCache(".")

	// 测试并发安全
	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			key := fmt.Sprintf("key%d", i)
			cache.SetWithExpire(key, fmt.Sprintf("value%d", i), time.Second*5)
		}(i)
	}
	wg.Wait()

	// 读取测试
	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("key%d", i)
		val, ok := cache.Get(key)
		fmt.Printf("%s: %s, exists: %v\n", key, val, ok)
	}

	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("key%d", i)
		expire, ok := cache.GetExpire(key)
		fmt.Printf("%s expired: %v,expireAt:%v  \n", key, !ok, expire)
	}

	// 持久化测试
	_ = cache.SaveToFile("cache.gob")
	fmt.Println("Saved to cache.gob")

	// 清空缓存，再加载
	cache = NewCache(".")
	_ = cache.LoadFromFile("cache.gob")
	fmt.Println("Loaded from cache.gob")

	// 检查是否恢复成功
	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("key%d", i)
		val, ok := cache.Get(key)
		fmt.Printf("%s: %s, exists: %v\n", key, val, ok)
	}

	// 保持运行，观察过期
	time.Sleep(6 * time.Second)
	for i := 0; i < 100; i++ {
		key := fmt.Sprintf("key%d", i)
		_, ok := cache.Get(key)
		fmt.Printf("%s expired: %v\n", key, !ok)
	}
}
